#![no_std]
#![no_main]
#![doc = include_str!("../README.md")]

#[macro_use]
extern crate axlog;

extern crate alloc;
extern crate axruntime;

#[cfg(feature = "vf2")]
extern crate axplat_riscv64_visionfive2;

#[cfg(feature = "opi5p")]
extern crate axplat_aarch64_opi5p;

use alloc::{borrow::ToOwned, vec::Vec};

use axfs_ng::FS_CONTEXT;

mod entry;

pub const CMDLINE: &[&str] = &["/bin/sh", "-c", include_str!("init.sh")];

// pub const CMDLINE: &[&str] = &[
//     "/bin/sh",
//     "-c",
//     r#"
// #!/bin/sh
// export HOME=/root
// echo -e "Welcome to \e[96m\e[1mStarry OS\e[0m!"
// env
// echo
// echo -e "Use \e[1m\e[3mapk\e[0m to install packages."
// echo
// cd ~
// sh --login
// "#,
// ];

#[unsafe(no_mangle)]
fn main() {
    ax_println!("start exec main function");

    starry_api::init();

    // Test GPIO LED blink before starting init process
    info!("======================================");
    info!("Testing GPIO LED Blink Demo");
    info!("======================================");
    test_led_blink();
    info!("======================================");
    info!("LED Blink Test Completed");
    info!("======================================");

    // Test I2C OLED Display
    info!("======================================");
    info!("Testing I2C OLED Display");
    info!("======================================");
    test_i2c_oled_display();
    info!("======================================");
    info!("I2C OLED Display Test Completed");
    info!("======================================");

    // Test MIPI DSI Display
    info!("======================================");
    info!("Testing MIPI DSI Display");
    info!("======================================");
    test_mipi_dsi_display();
    info!("======================================");
    info!("MIPI DSI Display Test Completed");
    info!("======================================");

    let args = CMDLINE
        .iter()
        .copied()
        .map(str::to_owned)
        .collect::<Vec<_>>();
    let envs = [];
    let exit_code = entry::run_initproc(&args, &envs);
    info!("Init process exited with code: {:?}", exit_code);

    let cx = FS_CONTEXT.lock();
    cx.root_dir()
        .unmount_all()
        .expect("Failed to unmount all filesystems");
    cx.root_dir()
        .filesystem()
        .flush()
        .expect("Failed to flush rootfs");
}

/// LED闪烁测试函数
/// 
/// 硬件连接:
/// GPIO4_C3 (物理引脚32) ----[ 330Ω 电阻 ]----[LED 正极]----[LED 负极]---- GND (引脚34)
#[cfg(feature = "opi5p")]
fn test_led_blink() {
    use axplat_aarch64_peripherals::rk3588_gpio::{
        GpioPin, GpioPinHandle, GpioDirection
    };
    
    info!("Initializing LED on GPIO4_C3 (Pin 32)...");
    
    // 创建 LED 控制句柄 (GPIO4_C3 = GPIO4 Pin 19)
    let mut led = GpioPinHandle::new(
        GpioPin::new(4, 19),  // GPIO4_C3
        GpioDirection::Output
    );
    
    info!("LED initialized, starting blink test...");
    info!("Connect LED: GPIO4_C3 (Pin 32) -> [330Ω] -> LED -> GND (Pin 34)");
    
    // 闪烁 10 次
    for i in 0..10 {
        info!("Blink {}/10 - LED ON", i + 1);
        led.set_high();
        axhal::time::busy_wait(core::time::Duration::from_millis(500)); // 500ms
        
        info!("Blink {}/10 - LED OFF", i + 1);
        led.set_low();
        axhal::time::busy_wait(core::time::Duration::from_millis(500)); // 500ms
    }
    
    info!("LED blink test completed successfully!");
}

#[cfg(not(feature = "opi5p"))]
fn test_led_blink() {
    info!("LED blink test is only available on Orange Pi 5 Plus");
    info!("Please build with: make opi5p");
}

/// I2C OLED 显示测试函数
/// 
/// 硬件连接 (以 SSD1306 128x64 OLED 为例):
/// SSD1306     ->  Orange Pi 5 Plus
/// VCC         ->  3.3V (引脚1或17)
/// GND         ->  GND (引脚6、9、14、20、25、30、34、39)
/// SCL         ->  I2C4_SCL / GPIO4_B5 (引脚28)
/// SDA         ->  I2C4_SDA / GPIO4_B6 (引脚27)
/// 
/// 注意: 需要确保 I2C4 已在设备树中启用
#[cfg(feature = "opi5p")]
fn test_i2c_oled_display() {
    use axplat_aarch64_peripherals::rk3588_i2c::{get_i2c, I2cController, I2cSpeed};
    use axplat_aarch64_peripherals::ssd1306::{Ssd1306, DisplaySize};

    info!("Initializing I2C4 controller...");
    
    // 初始化 I2C4 控制器（使用快速模式 400Kbps）
    let i2c = get_i2c(I2cController::I2C4, I2cSpeed::Fast);
    
    info!("I2C4 controller initialized");
    info!("Initializing SSD1306 OLED display at address 0x3C...");
    
    // 创建 SSD1306 显示驱动实例 (地址 0x3C, 128x64 显示)
    let mut display = Ssd1306::new(i2c, 0x3C, DisplaySize::Size128x64);
    
    // 初始化显示屏
    match display.init() {
        Ok(_) => {
            info!("SSD1306 display initialized successfully!");
            
            // 清空显示缓冲区
            let _ = display.clear();
            
            // 显示 "hello starryos" 在屏幕上
            info!("Drawing 'hello starryos' on display...");
            
            // 第一行显示 "hello starryos"
            display.draw_string(0, 0, "hello starryos");
            
            // 第二行显示一些额外信息
            display.draw_string(0, 10, "RK3588 I2C Demo");
            
            // 第三行显示日期/时间
            display.draw_string(0, 20, "2025-10-31");
            
            // 第四行显示一些装饰
            display.draw_string(0, 30, "================");
            
            // 第五行显示系统信息
            display.draw_string(0, 40, "Orange Pi 5+");
            
            // 第六行显示版本信息
            display.draw_string(0, 50, "StarryOS v1.0");
            
            // 更新显示
            match display.display() {
                Ok(_) => {
                    info!("Display updated successfully!");
                    info!("'hello starryos' is now shown on the OLED screen");
                    
                    // 保持显示 5 秒
                    info!("Keeping display on for 5 seconds...");
                    axhal::time::busy_wait(core::time::Duration::from_secs(5));
                    
                    // 测试闪烁效果
                    info!("Testing display blink effect...");
                    for i in 0..3 {
                        info!("Blink {}/3 - Display OFF", i + 1);
                        let _ = display.turn_off();
                        axhal::time::busy_wait(core::time::Duration::from_millis(500));
                        
                        info!("Blink {}/3 - Display ON", i + 1);
                        let _ = display.turn_on();
                        axhal::time::busy_wait(core::time::Duration::from_millis(500));
                    }
                    
                    // 测试反色显示
                    info!("Testing inverted display...");
                    let _ = display.invert(true);
                    axhal::time::busy_wait(core::time::Duration::from_secs(2));
                    let _ = display.invert(false);
                    
                    info!("OLED display test completed successfully!");
                }
                Err(e) => {
                    error!("Failed to update display: {:?}", e);
                }
            }
        }
        Err(e) => {
            error!("Failed to initialize SSD1306 display: {:?}", e);
            error!("Please check:");
            error!("1. Display is connected to I2C4 (SCL: Pin 28, SDA: Pin 27)");
            error!("2. Display address is 0x3C (or try 0x3D)");
            error!("3. Display is powered (VCC connected to 3.3V)");
            error!("4. I2C4 is enabled in device tree");
        }
    }
}

#[cfg(not(feature = "opi5p"))]
fn test_i2c_oled_display() {
    info!("I2C OLED display test is only available on Orange Pi 5 Plus");
    info!("Please build with: make opi5p");
}

/// MIPI DSI 显示测试函数
/// 
/// 硬件连接 (以 ILI9881C 800x1280 显示屏为例):
/// 显示屏       ->  Orange Pi 5 Plus
/// VCC (3.3V)  ->  3.3V 电源
/// GND         ->  GND
/// MIPI DSI    ->  DSI0 接口 (通过 FPC 排线连接)
/// 
/// 注意:
/// 1. MIPI DSI 显示屏通常需要专用的 FPC 连接器
/// 2. 需要在设备树中启用 DSI0 或 DSI1
/// 3. 可能需要配置背光 GPIO 和电源
/// 4. 不同型号的显示屏可能需要不同的初始化序列
#[cfg(feature = "opi5p")]
fn test_mipi_dsi_display() {
    use axplat_aarch64_peripherals::rk3588_mipi_dsi::{
        get_dsi, DsiController, DsiPhyConfig, DsiColorFormat,
    };
    use axplat_aarch64_peripherals::ili9881c::{Ili9881c, Ili9881cConfig};

    info!("Initializing MIPI DSI controller...");
    
    // 配置 DSI PHY (4通道, 500MHz HS时钟)
    let phy_config = DsiPhyConfig {
        lanes: 4,
        hs_clk_freq_mhz: 500,
    };
    
    // 获取 DSI0 控制器实例
    let dsi = get_dsi(
        DsiController::DSI0,
        phy_config,
        DsiColorFormat::Rgb888,
    );
    
    info!("DSI controller initialized");
    info!("Initializing ILI9881C display (800x1280)...");
    
    // 创建 ILI9881C 显示驱动实例
    let config = Ili9881cConfig {
        width: 800,
        height: 1280,
        lanes: 4,
    };
    
    let mut display = Ili9881c::new(dsi, config);
    
    // 初始化显示屏
    match display.init() {
        Ok(_) => {
            info!("ILI9881C display initialized successfully!");
            info!("Display resolution: {}x{}", display.width(), display.height());
            
            // 显示纯色测试
            info!("Filling display with colors...");
            
            // 红色
            info!("Displaying RED...");
            let _ = display.fill_color(0xFF0000);
            axhal::time::busy_wait(core::time::Duration::from_secs(2));
            
            // 绿色
            info!("Displaying GREEN...");
            let _ = display.fill_color(0x00FF00);
            axhal::time::busy_wait(core::time::Duration::from_secs(2));
            
            // 蓝色
            info!("Displaying BLUE...");
            let _ = display.fill_color(0x0000FF);
            axhal::time::busy_wait(core::time::Duration::from_secs(2));
            
            // 白色
            info!("Displaying WHITE...");
            let _ = display.fill_color(0xFFFFFF);
            axhal::time::busy_wait(core::time::Duration::from_secs(2));
            
            // 黑色
            info!("Displaying BLACK...");
            let _ = display.fill_color(0x000000);
            axhal::time::busy_wait(core::time::Duration::from_secs(2));
            
            // 测试显示开关
            info!("Testing display on/off...");
            for i in 0..3 {
                info!("Display OFF ({}/3)", i + 1);
                let _ = display.display_off();
                axhal::time::busy_wait(core::time::Duration::from_secs(1));
                
                info!("Display ON ({}/3)", i + 1);
                let _ = display.display_on();
                axhal::time::busy_wait(core::time::Duration::from_secs(1));
            }
            
            // 测试睡眠模式
            info!("Testing sleep mode...");
            info!("Entering sleep mode...");
            let _ = display.sleep();
            axhal::time::busy_wait(core::time::Duration::from_secs(2));
            
            info!("Waking up from sleep...");
            let _ = display.wake();
            let _ = display.display_on();
            
            info!("MIPI DSI display test completed successfully!");
            info!("Display is ready for use");
            
            // Note: 实际应用中，这里可以：
            // 1. 设置帧缓冲区
            // 2. 使用 DMA 传输像素数据
            // 3. 渲染图形和文本
            // 4. 显示 "hello starryos" 文本（需要图形库支持）
            
            info!("Note: To display 'hello starryos', integrate with a graphics library");
            info!("such as embedded-graphics or implement a framebuffer system");
        }
        Err(e) => {
            error!("Failed to initialize ILI9881C display: {:?}", e);
            error!("Please check:");
            error!("1. Display is properly connected to DSI0 interface");
            error!("2. Display power supply is correct (3.3V for logic)");
            error!("3. DSI0 is enabled in device tree");
            error!("4. Display model matches ILI9881C controller");
            error!("5. Timing parameters are correct for your panel");
        }
    }
}

#[cfg(not(feature = "opi5p"))]
fn test_mipi_dsi_display() {
    info!("MIPI DSI display test is only available on Orange Pi 5 Plus");
    info!("Please build with: make opi5p");
}
